package com.mcptt.config;

import android.content.Context;

import com.cloudptt.api.product.ILanChange;
import com.cloudptt.api.product.config.lbs.LocationConfig;
import com.cloudptt.api.product.func.addr.IAddrDefaultOp;
import com.cloudptt.api.product.func.sys.IRestartServer;
import com.cloudptt.api.product.log.Log;
import com.mcptt.config.callback.IAuthCallback;
import com.mcptt.config.callback.IParserCallback;
import com.mcptt.config.group.Group;
import com.mcptt.config.local.SysConfig;
import com.mcptt.config.model.McIdInfo;
import com.mcptt.config.service.CallPriority;
import com.mcptt.config.service.IServiceAttr;
import com.mcptt.config.service.Service;
import com.mcptt.config.ue.initial.CallTimer;
import com.mcptt.config.ue.initial.IUeInitAttr;
import com.mcptt.config.ue.initial.UeInitProfile;
import com.mcptt.config.ue.initial.sub.OnNetwork;
import com.mcptt.config.ue.initial.sub.sub.AnyExt;
import com.mcptt.config.ue.initial.sub.sub.AppServerInfo;
import com.mcptt.db.DBAdapter;
import com.mcptt.db.model.AddrInfo;
import com.mcptt.http.auth.process.HttpAuthFailedException;
import com.mcptt.http.auth.process.HttpProcessor;
import com.mcptt.http.auth.process.result.FinalResult;
import com.mcptt.http.auth.process.result.info.IdTokenResult;
import com.mcptt.notify.presence.PresenceParser;
import com.mcptt.notify.xcap.XcapParser;

import java.net.URI;
import java.net.URISyntaxException;

public class ConfigCenter implements IAuthCallback,IParserCallback
{
	private Context ctx = null;
	private SysConfig sysConfig = null;
	private LocationConfig locationConfig = null;
	private ConfigFilesManager configFilesManager = null;
	private DBAdapter dbAdapter = null;
	private ConfigListener listener = null;
	private IAuthCallback iCallback = null;
	private String idmsStr = null;
	private IParserCallback parserCallback = null;
	private HttpProcessor processor = null;
	private IAddrDefaultOp addrDefaultOp = null;

	public ConfigCenter(Context ctx, IRestartServer server, ILanChange lanChange, IAddrDefaultOp addrDefaultOp)
	{
		this.ctx = ctx;
		this.sysConfig = new SysConfig(ctx,server,lanChange);
		this.locationConfig = new LocationConfig(ctx);
		this.dbAdapter = new DBAdapter(ctx);
		this.addrDefaultOp = addrDefaultOp;
	}

	public void initMcpttConfig(ConfigListener listener)
	{
		Log.debug(this.getClass(),  "initMcpttConfig");
		this.listener = listener;
		if(sysConfig != null)
		{

			this.configFilesManager = new ConfigFilesManager(ctx,dbAdapter,sysConfig,addrDefaultOp);
//			String clientId = sysConfig.getClientId();
//			this.configFilesManager.initUeInitProfile(clientId,this);
			String mcId = sysConfig.getMcInfo().getAddrId();
			this.configFilesManager.initUeInitProfileForMcId(mcId,this);
		}
		else
		{
			Log.debug(this.getClass(),  "initMcpttConfig serverInfo = null");
		}
	}

//	public void getUserProfile(int mcType,ConfigListener listener)
//	{
//		Log.debug(this.getClass(),  "getUserProfile mcType = " + mcType);
//		this.listener = listener;
//		if(configFilesManager != null)
//		{
//			configFilesManager.getUserProfile(mcType,this);
//		}
//		else
//		{
//			Log.debug(this.getClass(),  "initMcpttConfig serverInfo = null");
//		}
//	}

	private HttpProcessor getHttpProcessor() throws URISyntaxException
	{
		Log.debug(this.getClass(), "getHttpProcessor");
		AbstractConfigFile configFile = this.configFilesManager.getConfigFileByFileType(UeInitProfile.FileName);
		if(configFile == null)
		{
			Log.debug(this.getClass(), "getHttpProcessor check return null 1");
			return null;
		}
		UeInitProfile ueInitProfile = (UeInitProfile)configFile;
		if(ueInitProfile.getOnNetwork() == null
				|| ueInitProfile.getOnNetwork().getAppServerInfo() == null)
		{
			Log.debug(this.getClass(), "getHttpProcessor check return null 2");
			return null;
		}
		AppServerInfo info = ueInitProfile.getOnNetwork().getAppServerInfo();
//		idmsStr = info.getIdms();
		String authUrl = info.getIdmsAuthEndpoint();
		String loginUrl = info.getIdmsLoginEndpoint();
		String tokenUrl = info.getIdmsTokenEndpoint();

		URI authUri = new URI(authUrl);
		URI loginUri = new URI(loginUrl);
		URI tokenUri = new URI(tokenUrl);
//		HttpProcessor processor = new HttpProcessor(HttpProcessor.Type_Acr_Digest,authUri,loginUri, tokenUri);//TEKE//SERVER DIFFERENT
		HttpProcessor processor = new HttpProcessor(HttpProcessor.Type_Acr_Password,authUri,loginUri, tokenUri);//MCS//SERVER DIFFERENT

		return processor;
	}
	public boolean checkMustParamOk()
	{
		if(this.sysConfig != null
				&& this.sysConfig.checkMustParamOk())
		{
			return true;
		}
		return false;
	}
//	public boolean checkAccessTokenExpire()
//	{
//		if(this.sysConfig != null
//				&& this.sysConfig.checkAccessTokenExpire())
//		{
//			return true;
//		}
//		return false;
//	}

	public void httpAuth(String mcId,String pwd,IAuthCallback iCallback)
	{
		Log.debug(this.getClass(), "httpAuth mcId = " + mcId);
//		if (this.sysConfig.checkAccessTokenExpire())
		{
			doHttpAuth(mcId,pwd,iCallback);
		}
	}

	private void updateAccessTokenAfterAuthSuc(FinalResult result)
	{
		Log.debug(this.getClass(), "updateAccessTokenAfterAuthSuc");
		if(sysConfig != null)
		{
			String accessToken = result.getAccessToken();
			String refreshToken = result.getRefreshToken();
			int expire = result.getExpires();
			this.sysConfig.setAccessTokenInfo(accessToken, refreshToken,expire);
			IdTokenResult idToken = result.getIdToken();
			if(idToken != null) {
				String mcpttId = idToken.getMcpttId();
				String mcvideoId = idToken.getMcvideoId();
				String mcDataId = idToken.getMcdataId();
				this.sysConfig.updateMcpttInfo(mcpttId,mcvideoId,mcDataId);
			}
			McIdInfo mcIdInfo = sysConfig.getMcInfo();
			configFilesManager.updateMcIdInfo(mcIdInfo);
		}
	}

	private void updateAccessTokenAfterRefreshSuc(FinalResult result)
	{
		Log.debug(this.getClass(), "updateAccessTokenAfterRefreshSuc");
		if(sysConfig != null)
		{
			String accessToken = result.getAccessToken();
			String refreshToken = result.getRefreshToken();
			int expire = result.getExpires();
			this.sysConfig.setAccessTokenInfo(accessToken, refreshToken,expire);
		}
	}

	private void doHttpAuth(String mcId,String pwd,IAuthCallback iCallback)
	{
		Log.debug(this.getClass(), "doHttpAuth mcId = " + mcId);
		this.iCallback = iCallback;
		try
		{
			processor = getHttpProcessor();
		} catch (URISyntaxException e1)
		{
			// TODO Auto-generated catch block
			Log.debug(this.getClass(), "doHttpAuth e1 = " + e1);
			e1.printStackTrace();
			notifyCallback(iCallback,IAuthCallback.Auth_Reg, HttpAuthFailedException.ErrCode_Exception,"" +e1.getClass());
		}

		if (processor != null
				&& this.sysConfig != null)
		{
			String clientId = this.sysConfig.getClientId();
			String redirectUri = this.sysConfig.getRedirectUri();
			processor.runAuthorizationThread(clientId, redirectUri,mcId, pwd,this);
		}
		else if (processor == null)
		{
			notifyCallback(iCallback,IAuthCallback.Auth_Reg,HttpAuthFailedException.ErrCode_Null,"processor == null");
		}
		else if (this.sysConfig == null)
		{
			notifyCallback(iCallback,IAuthCallback.Auth_Reg,HttpAuthFailedException.ErrCode_Null,"localConfig == null");
		}
	}


	public void doHttpRefreshToken(String refreshToken)
	{
		Log.debug(this.getClass(), "doHttpRefreshToken refreshToken = " + refreshToken);
		if (processor != null)
		{
			try
			{
			processor.runRefreshTokenThread(refreshToken,this);
			} catch (Exception e)
			{
				// TODO Auto-generated catch block
				Log.debug(this.getClass(), "doHttpRefreshToken e = " + e);
				e.printStackTrace();
				notifyCallback(iCallback,IAuthCallback.Auth_Refresh,HttpAuthFailedException.ErrCode_Exception,"" +e.getClass());
			}
		}
		else
		{
			notifyCallback(iCallback,IAuthCallback.Auth_Refresh,HttpAuthFailedException.ErrCode_Null,"processor == null");
		}
	}

	private void notifyCallback(IAuthCallback iCallback,int id,int code,String str)
	{
		if(iCallback != null)
		{
			iCallback.httpAuthFailed(id,code,str);
		}
	}

	//    public List<CalledInfo> getUserInfoList()
	//    {
	//	if(userProfile != null
	//		&& userProfile.getUserInfoList() != null)
	//	{
	//	    return userProfile.getUserInfoList();
	//	}
	//	return null;
	//    }
	//    
	//    public List<CalledInfo> getGroupInfoList()
	//    {
	//	if(userProfile != null
	//		&& userProfile.getGroupInfoList() != null)
	//	{
	//	    return userProfile.getGroupInfoList();
	//	}
	//	return null;
	//    }

	public SysConfig getSysConfig()
	{
		return sysConfig;
	}

	public LocationConfig getLocationConfig() {
		return locationConfig;
	}
	public AbstractConfigFile getConfigFileByFileType(String FileName)
	{
		return configFilesManager.getConfigFileByFileType(FileName);
	}
	public Group getGroupConfigFileByGroupName(String groupName)
	{
		return configFilesManager.getGroupConfigFileByGroupName(groupName);
	}

	public void recvNotify(String cmsUrl,String gmsUrl,String notifyStr,IParserCallback parserCallback)
	{
		Log.debug(getClass(), "recvNotify cmsUrl = " + cmsUrl + " gmsUrl = " + gmsUrl + " notifyStr = " + notifyStr);
		this.parserCallback = parserCallback;
		if(notifyStr.contains(XcapParser.Key))
		{
			String accessToken = getSysConfig().getMcInfo().getAccessToken();
			configFilesManager.recvXcapNotify(cmsUrl,gmsUrl,notifyStr,accessToken,this);
		}
		else if(notifyStr.contains(PresenceParser.Key))
		{
			configFilesManager.cleanOldPresence();
			configFilesManager.recvPresenceNotify(notifyStr,parserCallback);
		}
	}

	public CallConfig getDefaultCallConfig()
	{
		CallTimer callTimer = CallTimer.getDefaultCallTimer();
		CallPriority callPriority =  CallPriority.getDefaultCallPriority();
		return new CallConfig(callTimer, callPriority);
	}

	public CallConfig getCallConfig()
	{
		CallTimer callTimer = null;

		IUeInitAttr ueInitAttr = (IUeInitAttr)this.getConfigFileByFileType( UeInitProfile.FileName);
		if(ueInitAttr != null)
		{
			callTimer = ueInitAttr.getCallTimer();
		}
		if(callTimer == null)
		{
			callTimer = CallTimer.getDefaultCallTimer();
		}

		CallPriority callPriority = null;
		IServiceAttr serviceAttr = (IServiceAttr)this.getConfigFileByFileType( Service.FileName);
		if(serviceAttr != null)
		{
			callPriority = serviceAttr.getCallPriority();
		}
		if(callPriority == null)
		{
			callPriority = CallPriority.getDefaultCallPriority();
		}
		return new CallConfig(callTimer, callPriority);
	}

	@Override
	public void httpAuthSuc(int id,FinalResult result)
	{
		Log.debug(getClass(), "httpAuthSuc result = " + result);
		// TODO Auto-generated method stub
		//	 FinalResult result = doHttpAuth(mcId,pwd,iCallback);
		if(result != null
				&& result.isSuc())
		{
			if (result.checkReturnParamOk()) {
				updateAccessTokenAfterAuthSuc(result);
			}
			if(result.checkRefreshParamOk())
			{
				updateAccessTokenAfterRefreshSuc(result);
			}
			if(iCallback != null)
			{
				iCallback.httpAuthSuc(id,result);
			}
		}
		else
		{
			if(iCallback != null)
			{
				iCallback.httpAuthFailed(id,HttpAuthFailedException.ErrCode_Result_Err,"result err");
			}
		}
	}

	@Override
	public void httpAuthFailed(int id,int code,String errStr)
	{
		// TODO Auto-generated method stub
		if(iCallback != null)
		{
			iCallback.httpAuthFailed(id,code,errStr);
		}
	}


	@Override
	public void parserFileSuc(String fileName) {
		// TODO Auto-generated method stub
		Log.debug(getClass(), "parserFileSuc fileName = " + fileName);
		AbstractConfigFile file = (UeInitProfile)configFilesManager.getConfigFileByFileType(UeInitProfile.FileName);
		if(fileName != null
				&& fileName.equals(UeInitProfile.FileName))
		{
			UeInitProfile ueInitProfile = (UeInitProfile)file;
			Log.debug(getClass(), "parserFileSuc ueInitProfile = " + ueInitProfile + " checkMustParamOk() = " + ueInitProfile.checkMustParamOk());
			if(ueInitProfile.checkMustParamOk())
			{
				OnNetwork onNetwork = ueInitProfile.getOnNetwork();
				AnyExt anyExt = ueInitProfile.getOnNetwork().getAnyExt();
				String domain = ueInitProfile.getDomain();//onNetwork.getDomain();//
				Log.debug(getClass(), "parserFileSuc domain = " + domain);
				AddrInfo.setDomain(domain);
				String psiCms = anyExt.getCmsPsi().getServerURI();//onNetwork.getPsiCms();
//				psiCms = AddrInfo.toMcxPsi(psiCms,domain);
				String psiGms = onNetwork.getGmsUri();//.getPsiGms();
//				psiGms = AddrInfo.toMcxPsi(psiGms,domain);

				String psiMcPtt = anyExt.getMcpttPsi().getServerURI();//onNetwork.getPsiMcPtt();
//				psiMcPtt = AddrInfo.toMcxPsi(psiMcPtt,domain);
				String psiMcVideo = anyExt.getMcvideoPsi().getServerURI();//onNetwork.getPsiMcVideo();
//				psiMcVideo = AddrInfo.toMcxPsi(psiMcVideo,domain);
				String psiMcData = anyExt.getMcdataPsi().getServerURI();//onNetwork.getPsiMcData();
//				psiMcData = AddrInfo.toMcxPsi(psiMcData,domain);
				sysConfig.updateImsPsi(domain,psiCms,psiGms,psiMcPtt,psiMcVideo,psiMcData);

				AppServerInfo info = onNetwork.getAppServerInfo();
				String sbcUrl = info.getSbc();
				String dnsAddr = info.getDns();
				Log.debug(getClass(), "parserFileSuc sbcUrl = " + sbcUrl + " dnsAddr = " + dnsAddr);
				sysConfig.updateImsSbc(sbcUrl,dnsAddr);
				Log.debug(getClass(), "parserFileSuc mcIdInfo = " + sysConfig.getMcpttLoginInfo().getImsInfo());

				String httpProxy = info.getHttpProxy();
//				String gmsHttpUrl = info.getHttpProxy();
//				String idmsHttpUrl = info.getIdms();
				sysConfig.updateBootStrapSvrUrl(httpProxy);
				Log.debug(getClass(), "parserFileSuc ServerInfo = " + sysConfig.getMcpttLoginInfo().getBootStrapSvr());
			}
		}
		if(parserCallback != null)
		{
			parserCallback.parserFileSuc(fileName);
		}
		
		if(listener != null)
		{
			Log.debug(getClass(), "parserFileSuc file.checkMustParamOk() = " + file.checkMustParamOk());
//			if(file.checkMustParamOk())
			{
				listener.initConfigSuc(fileName);
			}
//			else
//			{
//				listener.initConfigFailed(fileName,"Missing key parameters.");
//			}
		}
	}


	@Override
	public void parserFileFailed(String fileName, String errStr) {
		// TODO Auto-generated method stub
		Log.debug(getClass(), "parserFileFailed fileName = " + fileName + " errStr = " + errStr);
		if(parserCallback != null)
		{
			parserCallback.parserFileFailed(fileName,errStr);
		}
		if(listener != null)
		{
			listener.initConfigFailed(fileName,errStr);
		}
	}

	public DBAdapter getDbAdapter() {
		return dbAdapter;
	}
	public void clearResource() {
		Log.debug(getClass(), "ConfigCenter clearResource");
		this.processor = null;
		this.parserCallback = null;
		this.idmsStr = null;
		this.iCallback = null;
		this.dbAdapter = null;
		this.configFilesManager = null;
		this.locationConfig = null;
		this.sysConfig = null;
		this.listener = null;
		this.ctx = null;
	}
}
